/*
 * Author: Kishore Reddy
 * Url: http://commonlibrarynet.codeplex.com/
 * Title: CommonLibrary.NET
 * Copyright: � 2009 Kishore Reddy
 * License: LGPL License
 * LicenseUrl: http://commonlibrarynet.codeplex.com/license
 * Description: A C# based .NET 3.5 Open-Source collection of reusable components.
 * Usage: Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ComLib.Entities;
using ComLib.Extensions;
using ComLib.LocationSupport;
using ComLib.ValidationSupport;
using ComLib.Types;
using ComLib.Feeds;


namespace ComLib.Web.Modules.Events
{
    /// <summary>
    /// Event entity.
    /// </summary>
    public partial class Event : ActiveRecordBaseEntity<Event>, IEntity, IPublishable
    {
        /// <summary>
        /// Gets the publish date.
        /// Used for RSS / Feed generation.
        /// </summary>
        /// <value>The publish date.</value>
        public DateTime PublishDate { get { return UpdateDate; } }


        /// <summary>
        /// Url for the slug. e.g. /my-latest-blog-post-with-different-url-than-default-title-48
        /// </summary>
        public string SlugUrl
        {
            get
            {
                return ComLib.Web.UrlSeoUtils.BuildValidUrl(Title) + "-" + Id;
            }
        }


        #region IPublishable
        /// <summary>
        /// Gets the author.
        /// </summary>
        /// <value>The author.</value>
        public string Author { get { return UpdateUser; } }


        /// <summary>
        /// Gets the relative link.
        /// </summary>
        /// <value>The relative link.</value>
        public string UrlRelative
        {
            get
            {
                return SlugUrl;
            }
        }


        /// <summary>
        /// Gets the absolute link.
        /// </summary>
        /// <value>The relative link.</value>
        public string UrlAbsolute
        {
            get
            {
                return "/" + SlugUrl;
            }
        }


        /// <summary>
        /// Gets the GUID.
        /// </summary>
        /// <value>The GUID.</value>
        public string GuidId
        {
            get { return UrlAbsolute; }
        }
        #endregion


        #region Validation
        /// <summary>
        /// Get the validator for validating this entity.
        /// </summary>
        /// <returns></returns>
        protected override IValidator GetValidatorInternal()
        {
            var val = new EntityValidator((validationEvent) =>
            {
                int initialErrorCount = validationEvent.Results.Count;
                IValidationResults results = validationEvent.Results;
                Event entity = (Event)validationEvent.Target;
                Validation.IsStringLengthMatch(entity.Title, false, true, true, 1, 150, results, "Title");
                Validation.IsStringLengthMatch(entity.Description, true, false, true, -1, 200, results, "Description");
                Validation.IsStringLengthMatch(entity.Content, false, true, false, 1, -1, results, "Content");
                Validation.IsStringRegExMatch(entity.Email, true, RegexPatterns.Email, results, "Email");
                Validation.IsStringRegExMatch(entity.Phone, true, RegexPatterns.PhoneUS, results, "Phone");
                Validation.IsStringRegExMatch(entity.Url, true, RegexPatterns.Url, results, "Url");
                Validation.IsStringLengthMatch(entity.Tags, true, false, true, -1, 80, results, "Tags");
                
                // Check the start date.
                if (!IsPersistant())
                {
                    Validation.IsDateWithinRange(entity.StartDate, true, true, DateTime.Today, DateTime.Today.AddDays(180), results, "StartDate");                    
                }

                // Check the end date is greater.
                Validation.IsDateWithinRange(entity.EndDate, true, true, entity.StartDate, entity.StartDate.AddDays(180), results, "EndDate");                

                // Check the time.
                Validation.IsNumericWithinRange(entity.StartTime, true, true, 0, 2400, results, "StartTime");
                Validation.IsNumericWithinRange(entity.EndTime, true, true, StartTime, 2400, results, "EndTime");
                
                return initialErrorCount == validationEvent.Results.Count;
            });
            return val;
        }
        #endregion


        #region Import/Export Setters
        /// <summary>
        /// Used for reflection based import. Set the start/end times as a string time range. e.g. 11:30am - 2:20pm
        /// </summary>
        public string Times
        {
            set
            {
                string val = value;
                TimeParseResult result = TimeHelper.ParseStartEndTimes(val);
                if (result.IsValid)
                {
                    StartTime = result.Start.ToMilitaryInt();
                    if (result.End != TimeSpan.MaxValue && result.End != TimeSpan.MinValue)
                        EndTime = result.End.ToMilitaryInt();
                }
                else Errors.Add("Start/End times are incorrect");
            }
        }


        /// <summary>
        /// Sets the starts.
        /// </summary>
        /// <value>The starts.</value>
        public string Starts
        {
            set
            {
                var result = TimeHelper.Parse(value);
                if (result.Success)
                    StartTime = result.Item.ToMilitaryInt();
                else
                    Errors.Add("Start Time", "Incorrect format");
            }
            get
            {
                return StartTime.TimeWithSuffix();
            }
        }


        /// <summary>
        /// Sets the Ends.
        /// </summary>
        /// <value>The Ends.</value>
        public string Ends
        {
            set
            {
                var result = TimeHelper.Parse(value);
                if (result.Success)
                    EndTime = result.Item.ToMilitaryInt();
                else
                    Errors.Add("End Time", "Incorrect format");
            }
            get
            {
                return EndTime.TimeWithSuffix();
            }
        }


        /// <summary>
        /// Used for reflection based Import.
        /// </summary>
        public string Costs
        {
            set
            {
                string val = value;
                if (string.IsNullOrEmpty(val))
                {
                    Cost = 0;
                    return;
                }
                val = val.Trim().ToLower();
                if (val == "do not know" || val == "don't know" || val == "zero" || val == "free" || val == "nothing" ||
                    val == "none" || val == "0" || val == "na" || val == "n/a" || val == "n.a" || val == "n.a." || val == "unknown")
                {
                    Cost = 0;
                    return;
                }
                if (val == "varies" || val == "depends" || val == "differs")
                {
                    Cost = -1;
                    return;
                }
                Cost = StringExtensions.ToDouble(val);
            }
        }
        #endregion


        #region Life-Cycle Events
        /// <summary>
        /// Handle life-cycle event.
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public override bool OnBeforeSave(object ctx)
        {
            if (StartDate == DateTime.MinValue)
                StartDate = DateTime.Now;
            if (EndDate == DateTime.MinValue || EndDate == DateTime.MaxValue)
                EndDate = DateTime.Now;
            return true;
        }
        #endregion
    }
}
